/*
 * z80_addressingModes.cpp
 *
 *  Created on: Jan 14, 2012
 *      Author: douglas
 */

#include "z80.hpp"


//implicitAddressing /////////////////////////////////////////////////////////
template <void (z80::*op_instruction)()>                                    //
inline void  z80::implicitAddressing8()                                     //
{
    regs.s = *regs.r[opcode.sourceReg];                                     //
	call(op_instruction);                                                   //
}                                                                           //
                                                                            //
template <u8 indirectReg, void (z80::*op_instruction)()>                    //
inline void  z80::implicitAddressing8_manual()                              //
{
	regs.s = *regs.r[indirectReg];                                          //
	call(op_instruction);                                                   //
}                                                                           //
                                                                            //
template <u8 pairIdxReg, void (z80::*op_instruction)()>                     //
inline void  z80::implicitAddressing16()                                    //
{                                                                           //
    regs.ss = *regs.pair[pairIdxReg];                                       //
	call(op_instruction);                                                   //
}                                                                           //
//////////////////////////////////////////////////////////////////////////////



//immediateAddressing/////////////////////////////////////////////////////////
template <void (z80::*op_instruction)()>
inline void  z80::immediateAddressing()
{
	regs.s = fetchPC(3);
	call(op_instruction);
}

template <void (z80::*op_instruction)()>
inline void  z80::immediateAddressing16()
{
	regs.ss = fetchPC(3);
	regs.ss |= fetchPC(3) << 8;
	call(op_instruction);
}
//////////////////////////////////////////////////////////////////////////////





//indirectAddressing//////////////////////////////////////////////////////////
//There are two Indirect Addressing Modes.
//The first uses the content of a pair register to read a byte from memory. I called
//this indirectAddressingRead.
//The second uses the content of a pair register as a destination address for a data
//to be writen in memory. I called this indirectAddressingWrite.

template <u8 indirectReg, void (z80::*op_instruction)()>
inline void  z80::indirectAddressingRead()
{
	regs.s = read8(*regs.pair[indirectReg], 3);
	//Here z80 only load the address on ss to be used by opcodes.
	//The write is done in the opcode methods.
	regs.ss = *regs.pair[indirectReg];
	call(op_instruction);
}

template <u8 indirectReg, void (z80::*op_instruction)()>
inline void  z80::indirectAddressingWrite()
{
    assert(indirectReg<6);
	//Here z80 only load the address on ss to be used by opcodes.
	//The write is done in the opcode methods.
	regs.ss = *regs.pair[indirectReg];
	call(op_instruction);
}
//////////////////////////////////////////////////////////////////////////////





//indexedAddressing///////////////////////////////////////////////////////////
template <u8 idxReg, void (z80::*op_instruction)()>
inline void  z80::indexedAddressing()
{
	displacement = fetchPC(3);
    regs.s = read8(*regs.pair[idxReg] + displacement, 3);
	call(op_instruction);
}

template <u8 idxReg, void (z80::*op_instruction)()>
inline void  z80::indexedAddressingWrite()
{
	displacement = fetchPC(3);
    regs.ss = *regs.pair[idxReg] + displacement;
	call(op_instruction);
}
//////////////////////////////////////////////////////////////////////////////


//immediateAddressing/////////////////////////////////////////////////////////
template <void (z80::*op_instruction)()>
inline void  z80::relativeAddressing()
{
	regs.s = fetchPC(3);
	call(op_instruction);
}


//directAddressing/////////////////////////////////////////////////////////
template <void (z80::*op_instruction)()>
inline void  z80::directAddressing()
{
	regs.s = fetchPC(3);
	call(op_instruction);
}

template <void (z80::*op_instruction)()>
inline void  z80::directAddressing16()
{
	regs.ss = fetchPC(3);
	regs.ss |= fetchPC(3) << 8;
	call(op_instruction);
}
//////////////////////////////////////////////////////////////////////////////


template <u8 externalReg, void (z80::*op_instruction)()>
inline void  z80::externalAddressing16()
{
	regs.s = read8(*regs.pair[externalReg], 3);
	call(op_instruction);
}


template <void (z80::*op_instruction)()>                                    //
inline void  z80::externalAddressing8()                                     //
{                                                                           //
	regs.s = *regs.r[opcode.destReg];                                       //
	call(op_instruction);                                                   //
}











